﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using S7.Net;      // 西门子PLC通信库
using Sql;         // 自定义SQL库

using System.IO;
using System.Windows.Forms.DataVisualization.Charting;   // 图表控件
using Helper;      // 自定义帮助类
using System.Collections;
using System.Text.RegularExpressions;   // 正则表达式
using NPOI.HSSF.UserModel;              // Excel操作库


using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using USB2XXX;                // USB设备操作库
using System.Net.Sockets;     // 网络通信
using NModbus.Device;         // Modbus协议库
using NModbus;

namespace BaseVisual
{
    public class BaseClass1
    {


        // 模温机通信参数
        public static string _ipAddress = "192.168.1.101";  // PLC的IP地址
        public static int _port = 502;                      // Modbus TCP默认端口
        public static TcpClient _tcpClient;                 // TCP客户端
        public static ModbusIpMaster _master;               // Modbus主站
        public static bool _isConnected = false;            // 连接状态

        // 数据存储数组
        public ushort[] MWJ_Data=new ushort[80];             // 模温机数据存储数组，80个无符号短整型
        public string[] SaveTime = new string[1] { @"D:\时间记录" };   // 时间记录路径数组

        // 温度相关
        public float[] Temperature_Time = new float[20];// 温度时间数据数组，10个浮点数
        public float Set_Temperature;                   // 设定温度
        public int ConnectState_Analog;                 //采集卡连接状态

        // LIN通信相关
        public byte[] ID0 = new byte[2] { 0x2A, 0x29 };      // LIN发送/读取ID数组，第一个字节为发送ID，第二个为读取ID
        public byte[] ID1 = new byte[2] { 0x2A, 0x29 };      // 另一个LIN通道的ID数组
        public Int32[] DevHandles = new Int32[22];           // 设备句柄数组，存储扫描到的设备句柄
        public Int32[] DevHandle = new Int32[22];            // 实际使用的设备句柄数组
        public Byte[] LINIndex = new byte[4] { 0, 1, 2, 3 }; // LIN通道索引数组
        public string[] LINState = new string[10];           // LIN状态信息数组，存储各步骤状态
        public bool LINStateOK;                              // LIN总体状态OK标志
        public Int32 DevNum, ret, ret1 = 0;                  // 设备数量、返回值、返回值1
        public Int32[] ret11 = new Int32[22];                // 返回值数组，用于存储多个操作返回值
        public byte[] DataBuffer_Read;                       // 数据读取缓冲区
        public string[] Lin_Name = new string[22];           // LIN设备名称数组
        public int Lin_Num;                                  // LIN设备数量

        // 手动操作相关
        public int[] Man_Action = new int[50];    // 手动操作数组，存储50个手动操作状态


        // LIN数据缓冲区
        public static byte[][] DataBuffersArrayLIN = new byte[50][];   // LIN数据缓冲区二维数组
        public static string[][] LINRArrays = new string[50][];        // LIN接收数据二维数组
        public string[] LINReceive = new string[50];                   // LIN接收数据数组


        // LIN数据缓冲区定义（0-9），每个缓冲区2字节
        public static byte[] DataBuffer_0 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_1 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_2 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_3 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_4 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_5 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_6 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_7 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_8 = new byte[2] { 0x00, 0x00 };
        public static byte[] DataBuffer_9 = new byte[2] { 0x00, 0x00 };


        // LIN接收数据数组，每个数组9个字符串元素
        public string[] LINR0 = new string[9];
        public string[] LINR1 = new string[9];
        public string[] LINR2 = new string[9];
        public string[] LINR3 = new string[9];
        public string[] LINR4 = new string[9];
        public string[] LINR5 = new string[9];
        public string[] LINR6 = new string[9];
        public string[] LINR7 = new string[9];
        public string[] LINR8 = new string[9];
        public string[] LINR9 = new string[9];


        public string[] LIN_SendStr = new string[10];   // LIN发送字符串数组


        //程控电源// 设备控制命令
        public string Power_Start = "01 10 00 09 00 01 02 00 03 E6 C8";  // 电源启动Modbus命令
        public string Power_Stop = "01 10 00 09 00 01 02 00 02 27 08";   // 电源停止Modbus命令
        //模拟量采集模块命令
        public string AnalogSend = "01 03 00 00 00 20 44 12";            // 模拟量读取Modbus命令


        // 电气参数
        public int CurrentMax;    // 最大电流
        public int VoltageMax;    // 最大电压


        //设备型号Type
        public string DeviceType;// 设备型号字符串

        // 状态数组
        public bool[] State = new bool[50];  // 通用状态布尔数组，50个元素


        //测试模式
        public int[] TsetMode = new int[6];  // 测试模式设置数组，6个整型

        // 报警系统
        public int[] AlarmInt = new int[6];      // 报警代码数组
        public string[] Alarm = new string[50];  // 报警信息字符串数组


        // PLC通信对象
        public Plc PLC1 = new Plc(CpuType.S71200, "192.168.1.10", 0, 1);  // 西门子PLC实例
        public bool PLCState;                         // PLC连接状态
        public bool[] PLC_TO_OPC = new bool[72];      // PLC到OPC数据传输数组
        public bool[] OPC_TO_PLC = new bool[16];      // OPC到PLC数据传输数组


        // 测试参数上下限数组
        public float[] CurrentDown = new float[6];        // 电流下限数组
        public float[] CurrentUP = new float[6];          // 电流上限数组
        public float[] VoltageDown = new float[6];        // 电压下限数组
        public float[] VoltageUP = new float[6];          // 电压上限数组
        public float[] InPowerDown = new float[6];        // 输入功率下限数组
        public float[] InPowerUp = new float[6];          // 输入功率上限数组
        public float[] FlowDown = new float[6];           // 流量下限数组
        public float[] FlowUP = new float[6];             // 流量上限数组
        public float[] OutpressureDown = new float[6];    // 出口压力下限数组
        public float[] OutpressureUp = new float[6];      // 出口压力下限数组
        public float[] InputpressureDown = new float[6];  // 出口压力下限数组
        public float[] InputpressureUp = new float[6];    // 出口压力下限数组

        // 测试数据数组
        public int level;        // 等级标识
        public float[] Current = new float[6];    // 电流测量值数组
        public float[] Voltage = new float[6];    // 电压测量值数组
        public float[] Input_pressure = new float[6] { -1, -1, -1, -1, -1, -1 };   // 进口压力数组，初始值为-1
        public float[] Output_pressure = new float[6];   // 出口压力数组
        public float[] Diff_pressure = new float[6];     // 压差数组    
        public float[] Flow = new float[6];              // 流量数组
        public float[] Temperature = new float[7];       // 温度数组，7个测量点
        public float[] Box_pressure = new float[3];      // 箱体压力数组
        public float[] InPower = new float[6];           // 输入功率数组


        // 性能参数
        public double YC_Lift;         //扬程计算结果
        public double IN_Power;        //输入功率计算结果
        public double OUT_Power;       //输出功率计算结果
        public double XL_ratio;        //效率计算结果
        public int Speed;              // 转速测量值
        public float Pressure_Diff;    // 压差测量值
        public ushort ReSet_BTN;       // 复位按钮状态

        // 其他参数
        public float[] LSX = new float[3] { 0, 0, 0 };     // 临时数组数组
        public int[] PressureAlarm = new int[2] { 0, 0 };  // 压力报警数组
        public int[] Step = new int[6];       // 步序数组
        public int[] BTNState = new int[2];   // 按钮状态数组
        public int[] Emer = new int[3];       // 紧急状态数组

        // 数据采集列表
        public List<float> CurrentList0 = new List<float>();         //采集电流数据列表
        public List<float> InPressureList0 = new List<float>();      //采集进口压力数据列表
        public List<float> OutPressureList0 = new List<float>();     //采集出口压力数据列表
        public List<float> PressureDiffList0 = new List<float>();    //采集压差数据列表
        public List<double> CollectFlowList0 = new List<double>();   //采集流量数据列表
        public List<double> CountLift0 = new List<double>();         // 扬程计算结果列表
        public List<double> InputPower0 = new List<double>();        //输入功率计算结果列表
        public List<double> OutPower0 = new List<double>();          //输出功率计算结果列表
        public List<double> MotorRatio0 = new List<double>();        // 电机效率计算结果列表
        public List<float> ActualSpeed0 = new List<float>();         //实际转速测量列表
        public List<float> Voltage0 = new List<float>();             //电压测量列表
        public List<float> TemperatureList = new List<float>();      //温度测量列表


        // 文件路径
        public string[] SavePT = new string[4] { @"D:\耐久测试", @"D:\启停测试1", @"D:\启停测试2", @"D:\启停测试3" };  // 数据保存路径
        public string[] ReadPT = new string[2] { @"C:\VM\1\1.jpg", @"C:\VM\2\1.jpg" };   // 图片读取路径
        public string[] DeletPT = new string[2] { @"C:\VM\1", @"C:\VM\2" };              // 文件删除路径


        public bool[] DataSaveBool = new bool[2];// 数据保存标志数组


        // 扫码相关控件和变量
        static int num = 6;            // 扫码相关控件数量
        public Label[] labelContol = new Label[num];       // 标签控件数组
        public CheckBox[] CBox = new CheckBox[num];        // 复选框控件数组
        public string[] CodeStrExist = new string[num];    // 存在的代码字符串数组

        // 配方参数
        public string[] RecipeParameter = new string[400];   // 配方参数字符串数组，400个参数
        public float[] Parameterfloat = new float[400];      // 配方参数数值数组，400个浮点数
        public float cycle0 , cycle1 , cycle2;               // 周期参数，三个不同的周期值

        // 文件路径
        public string RecipePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Recipe");    // 配方文件路径
        public string ReadEXcll = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "1.xlsm");     // Excel模板文件路径


        // 计数器和时间相关
        public int[] Count = new int[2];              // 通用计数器数组
        public ushort NG_Line_Count;                  // NG线计数
        public int[] Collection_Time = new int[13];   // 采集时间数组
        public string[] DataList = new string[10] { "电压(V)", "电流(A)", "流量(L/min)", "扬程(m)", "压差(Kpa)", "进口压力(Kpa)", "介质温度(°C)", "输入功率(W)", "输出功率(W)", "效率(%)" };    // 数据显示标签

        // 生产线信息
        public string[] FLName = new string[1];    // 生产线名称数组
        public string[] FLID = new string[1];      // 生产线ID数组
        public string FL_ID = " / ";               // 生产线ID显示字符串
        public string FL_Name = " / ";             // 生产线名称显示字符串


        // 生产统计
        public int Left_yield;              // 左工位总产量
        public int Right_yield;             // 左工位总产量
        public int Left_Qualified_Num;      // 左工位合格数
        public int Left_NO_Qualified_Num;   // 左工位不合格数
        public int Right_Qualified_Num;     // 右工位合格数
        public float Left_Qualified_Rate;   // 左工位合格率
        public float Right_Qualified_Rate;  // 右工位合格率

        // 时间记录变量
        public string Time;                  // 当前时间字符串
        public static DateTime[] StartTime = new DateTime[6];   // 开始时间数组
        public static DateTime EndTime;      // 结束时间
        public static TimeSpan[] difference = new TimeSpan[6];  // 时间差数组




        // 启停测试时间记录数组
        public static DateTime[] StartTime0 = new DateTime[6];
        public static DateTime[] StartTime1 = new DateTime[6];
        public static DateTime[] StartTime2 = new DateTime[6];
        public static DateTime[] StartTime3 = new DateTime[6];

        // 启停测试时间差数组
        public static TimeSpan[] difference0 = new TimeSpan[6];
        public static TimeSpan[] difference1 = new TimeSpan[6];
        public static TimeSpan[] difference2 = new TimeSpan[6];
        public static TimeSpan[] difference3 = new TimeSpan[6];

        // 状态标志数组，用于各种状态记录
        public int[] ZJbool0 = new int[50];
        public int[] ZJbool1 = new int[50];
        public int[] ZJbool2 = new int[50];
        public int[] ZJbool3 = new int[50];
        public int[] ZJbool4 = new int[50];
        public int[] ZJbool5 = new int[50];


        public string[] PathStr = new string[6] { "", "", "", "", "", "" };   //路径字符串


        //扫码枪
        public string CodeStr = "";        // 扫描到的代码字符串
        public string[] StationCodeStr = new string[2] { "", "" };    // 工位代码字符串数组


        // SQL数据库对象
        public SQL SQL1 = new SQL();   // SQL操作实例

        // 视觉检测相关
        public string[] TestResult = new string[2] { "", "" };   // 测试结果数组
        public string SendStr = "T2";                            // 发送给相机的命令字符串
        public int ProInt;                                       // 进度整数
        public ushort[] AlarmPLC = new ushort[2];                // PLC报警代码数组
        public ushort[] RunTime = new ushort[2];                 // 运行时间数组


        /// <summary>
        /// 标签控件状态设置
        /// </summary>
        /// <param name="LB">标签控件</param>
        /// <param name="Idex">状态索引</param>
        /// <param name="Str">显示文本</param>
        public void LBControl(Label LB, int Idex, string Str)
        {
            switch (Idex)
            {
                case 1:       // 绿色-正常
                    LB.BackColor = Color.Green;
                    LB.Text = Str;
                    break;
                case 2:      // 红色-异常
                    LB.BackColor = Color.Red;
                    LB.Text = Str;
                    break;
                case 3:      // 黄色-警告
                    LB.BackColor = Color.Yellow;
                    LB.Text = Str;
                    break;
                case 4:      // 灰色-禁用
                    LB.BackColor = Color.Gray;
                    LB.Text = Str;
                    break;
                case 5:      // 只更新文本
                    LB.Text = Str;
                    break;
            }
        }

        /// <summary>
        /// 获取复选框状态
        /// </summary>
        /// <param name="C1">复选框</param>
        /// <returns>"1"选中，"0"未选中</returns>
        public string CheckBoxState(CheckBox C1)
        {
            if (C1.Checked)
            {
                return "1";
            }
            else
            {
                return "0";
            }
        }

        /// <summary>
        /// 根据状态设置复选框
        /// </summary>
        /// <param name="State">状态字符串</param>
        /// <param name="C1">复选框</param>
        public void CheckBoxFeedback(string State, CheckBox C1)
        {
            if (State == "1")
            {
                C1.Checked = true;
            }
            else
            {
                C1.Checked = false;
            }
        }






        /// <summary>
        /// 连接Modbus TCP设备
        /// </summary>
        public static void Connect()
        {
            try
            {
                _tcpClient = new TcpClient(_ipAddress, _port);

                var factory = new ModbusFactory();
                _master = (ModbusIpMaster)factory.CreateMaster(_tcpClient);

                _isConnected = true;
            }
            catch (Exception ex)
            {
                _isConnected = false;
                throw;
            }
        }

        /// <summary>
        /// 读取寄存器（地址从0开始）
        /// </summary>
        /// <param name="startAddress">起始地址（0=40001）</param>
        /// <param name="count">寄存器数量</param>
        public static ushort[] ReadRegisters(ushort startAddress, ushort count)
        {
            if (!_isConnected)
                throw new Exception("未连接PLC");

            return _master.ReadHoldingRegisters(startAddress, count);
        }


        /// <summary>
        /// 写入寄存器（地址从0开始）
        /// </summary>
        /// <param name="startAddress">起始地址（0=40001）</param>
        /// <param name="values">要写入的值</param>
        public static void WriteRegisters(ushort startAddress, ushort[] values)
        {
            if (!_isConnected)
                throw new Exception("未连接PLC");

            _master.WriteMultipleRegisters(startAddress, values);
        }


        /// <summary>
        /// 检查连接状态
        /// </summary>
        /// <returns>连接是否正常</returns>
        public static bool CheckConnection()
        {
            if (!_isConnected || _tcpClient == null || !_tcpClient.Connected)
                return false;

            // 发送测试请求（可选：读取一个寄存器验证连接）
            try
            {
                _master.ReadHoldingRegisters(0, 1); // 读取1个寄存器测试
                return true;
            }
            catch
            {
                return false;
            }
        }



        // ========== PLC通信方法 ==========

        /// <summary>
        /// 打开PLC连接
        /// </summary>
        /// <returns>连接状态</returns>
        public bool PlcOpen()
        {

            if (!PLC1.IsConnected)
            {
                PLCState = false;
                PLC1.OpenAsync().Wait(500);     // 异步打开，等待500ms

            }
            else
            {
                PLCState = true;
            }
            return PLCState;

        }


        /// <summary>
        /// 关闭PLC连接
        /// </summary>
        public void PlcColse()
        {
            try
            {
                PLC1.Close();
            }
            catch (Exception) { }
        }
        public void ReadPLC()
        {
            // 读取步序
            Step[0] = (ushort)PLC1.Read("DB1.DBW300");
            Step[1] = (ushort)PLC1.Read("DB1.DBW302");
            Step[2] = (ushort)PLC1.Read("DB1.DBW304");
            Step[3] = (ushort)PLC1.Read("DB1.DBW306");
            Step[4] = (ushort)PLC1.Read("DB1.DBW308");
            Step[5] = (ushort)PLC1.Read("DB1.DBW310");

            // 读取输入状态
            State[0] = (bool)PLC1.Read("DB1.DBX206.0");//I0.0
            State[1] = (bool)PLC1.Read("DB1.DBX206.1");
            State[2] = (bool)PLC1.Read("DB1.DBX206.2");
            State[3] = (bool)PLC1.Read("DB1.DBX206.3");
            State[4] = (bool)PLC1.Read("DB1.DBX206.4");//回水液位高位
            State[5] = (bool)PLC1.Read("DB1.DBX206.5");//回水液位低位
            State[6] = (bool)PLC1.Read("DB1.DBX206.6");//主罐液位低位
            State[22] = (bool)PLC1.Read("DB1.DBX206.7");//主罐液位高位


            // 读取输出状态
            State[7] = (bool)PLC1.Read("DB1.DBX204.0");//Q0.0
            State[8] = (bool)PLC1.Read("DB1.DBX204.1");
            State[9] = (bool)PLC1.Read("DB1.DBX204.2");
            State[10] = (bool)PLC1.Read("DB1.DBX204.3");
            State[11] = (bool)PLC1.Read("DB1.DBX204.4");
            State[12] = (bool)PLC1.Read("DB1.DBX204.5");
            State[13] = (bool)PLC1.Read("DB1.DBX204.6");
            State[14] = (bool)PLC1.Read("DB1.DBX204.7");
            State[15] = (bool)PLC1.Read("DB1.DBX205.0");//Q1.0
            State[16] = (bool)PLC1.Read("DB1.DBX205.1");
            State[17] = (bool)PLC1.Read("DB1.DBX205.2");
            State[18] = (bool)PLC1.Read("DB1.DBX205.3");
            State[19] = (bool)PLC1.Read("DB1.DBX205.4");
            State[20] = (bool)PLC1.Read("DB1.DBX205.5");
            State[21] = (bool)PLC1.Read("DB1.DBX205.6");
            State[22] = (bool)PLC1.Read("DB1.DBX205.7");//冷却


            // 读取特殊状态
            State[27] = (bool)PLC1.Read("DB1.DBX200.2");//复位
            State[28] = (bool)PLC1.Read("DB1.DBX203.2");//液位过低报警
            State[29] = (bool)PLC1.Read("DB1.DBX200.4");//急停
            State[30] = (bool)PLC1.Read("DB1.DBX200.1");//运行中

            WiterPLCBool(30, true);          // 写入心跳信号


            // 温度控制
            if (ConnectState_Analog < 5)
            {
                WiterPLC0(0, Set_Temperature);    // 写入设定温度
                WiterPLC0(1, Temperature[0]);     // 写入当前温度
            }
        }


        /// <summary>
        /// 写入PLC浮点数数据
        /// </summary>
        /// <param name="Idex">索引</param>
        /// <param name="Value">值</param>
        public void WiterPLC0(int Idex, float Value)
        {
            string ConStr = "";
            switch (Idex)
            {
                case 0:
                    ConStr = "DB1.DBD500";   //设定温度
                    break;
                case 1:
                    ConStr = "DB1.DBD504";   //当前温度
                    break;
            }
            PLC1.Write(ConStr, (float)Value);  // 执行写入操作
        }


        /// <summary>
        /// 写入PLC控制逻辑
        /// 根据温度条件和配方参数控制加热、冷却和控温使能
        /// </summary>
        public void WiterPLC()
        {
            // 温度低于设定温度-2度且采集卡连接正常时，开启加热
            if (Temperature[0] < (Set_Temperature - 2) && ConnectState_Analog < 5)//加热
            {
                WiterPLCBool(28, true);   // 开启加热
            }
            else
            {
                WiterPLCBool(28, false);  // 关闭加热
            }

            // 温度高于设定温度+2度且采集卡连接正常时，开启冷却
            if (Temperature[0] > (Set_Temperature + 2) && ConnectState_Analog < 5)   //冷却
            {
                WiterPLCBool(29, true);   // 开启冷却
            }
            else
            {
                WiterPLCBool(29, false);  // 关闭冷却
            }

            // 根据配方参数370决定是否启用控温
            if (RecipeParameter[370] == "1")
            {
                WiterPLCBool(35, true);   // 启用控温
            }
            else
            {
                WiterPLCBool(35, false);  // 禁用控温
            }
            WiterPLCBool(30, true);       // 写入心跳信号，保持连接
        }


        /// <summary>
        /// 写入PLC整型数据
        /// </summary>
        /// <param name="Idex">数据类型索引</param>
        /// <param name="Value">要写入的整数值</param>
        public void WiterPLCint(int Idex, short Value)
        {
            string ConStr = "";       // PLC地址字符串

            switch (Idex)
            {
                case 0://步序
                    ConStr = "DB1.DBW400";  // 步序控制地址

                    break;
                case 1://入口电磁阀
                    ConStr = "DB1.DBW404";  // 入口电磁阀控制地址

                    break;
                case 2://出口电磁阀
                    ConStr = "DB1.DBW406";  // 出口电磁阀控制地址
                    break;
                case 3://启停通断
                    ConStr = "DB1.DBW410";  // 启停控制地址
                    break;
                case 4://员工ID
                    ConStr = "DB1.DBW294";   // 员工ID存储地址
                    break;
            }
            PLC1.Write(ConStr, (short)Value);   // 执行PLC写入操作
        }


        /// <summary>
        /// 写入设备启停状态到PLC
        /// </summary>
        /// <param name="Idex">设备索引</param>
        /// <param name="Value">启停状态值</param>
        public void WiterStart_Stop(int Idex, short Value)
        {
            string ConStr = "";               // PLC地址字符串

            switch (Idex)
            {
                case 0://OP1启停
                    ConStr = "DB1.DBW370";    // OP1工位启停地址

                    break;
                case 1://OP2启停
                    ConStr = "DB1.DBW372";    // OP2工位启停地址

                    break;
                case 2://OP3启停
                    ConStr = "DB1.DBW374";    // OP3工位启停地址

                    break;
                case 3://OP4启停
                    ConStr = "DB1.DBW376";    // OP4工位启停地址
                    break;

                case 4://OP5启停
                    ConStr = "DB1.DBW378";    // OP5工位启停地址
                    break;
                case 5://OP6启停
                    ConStr = "DB1.DBW380";    // OP6工位启停地址
                    break;
            }
            PLC1.Write(ConStr, (short)Value);  // 执行PLC写入操作
        }



        /// <summary>
        /// 写入测试完成状态到PLC
        /// </summary>
        /// <param name="Station">工站编号</param>
        /// <param name="Value">完成状态值</param>
        public void WiterPLCcomplete(int Station, short Value)
        {
            string ConStr = "";    // PLC地址字符串

            switch (Station)
            {
                case 0://OP1测试完成
                    ConStr = "DB1.DBW300";  // OP1测试完成状态地址

                    break;
                case 1://OP2测试完成
                    ConStr = "DB1.DBW302";  // OP2测试完成状态地址

                    break;
                case 2:// 
                    ConStr = "DB1.DBW304";  // OP3测试完成状态地址
                    break;
                case 3:// 
                    ConStr = "DB1.DBW306";  // OP4测试完成状态地址
                    break;
                case 4:// 
                    ConStr = "DB1.DBW308";  // OP5测试完成状态地址
                    break;
                case 5:// 
                    ConStr = "DB1.DBW310";  // OP6测试完成状态地址
                    break;
            }
            PLC1.Write(ConStr, (short)Value);  // 执行PLC写入操作
        }

        /// <summary>
        /// 写入PLC布尔值
        /// </summary>
        /// <param name="Idex">索引</param>
        /// <param name="Value">布尔值</param>
        public void WiterPLCBool(int Idex, bool Value)
        {
            string ConStr = "";
            switch (Idex)
            {
                case 1:      // 手动模式
                    ConStr = "DB1.DBX200.0";
                    break;
                case 5:      // OP1泵启动 
                    ConStr = "DB1.DBX330.0"; //OP1泵启动
                    break;
                case 6://
                    ConStr = "DB1.DBX332.0"; //OP2泵启动
                    break;
                case 7://
                    ConStr = "DB1.DBX334.0"; //OP3泵启动
                    break;
                case 8://
                    ConStr = "DB1.DBX336.0"; //OP4泵启动
                    break;
                case 9://
                    ConStr = "DB1.DBX338.0"; //OP5泵启动
                    break;
                case 10://
                    ConStr = "DB1.DBX340.0"; //OP6泵启动
                    break;
                case 11://
                    ConStr = "DB1.DBX201.0"; //OP1泵启动
                    break;
                case 12://
                    ConStr = "DB1.DBX201.1"; //OP2泵启动
                    break;
                case 13://
                    ConStr = "DB1.DBX201.2"; //OP3泵启动
                    break;
                case 14://
                    ConStr = "DB1.DBX201.3"; //OP4泵启动
                    break;
                case 15://
                    ConStr = "DB1.DBX201.4"; //OP5泵启动
                    break;
                case 16://
                    ConStr = "DB1.DBX201.5"; //OP6泵启动
                    break;
                case 23://
                    ConStr = "DB1.DBX348.0"; //电加热
                    break;
                case 24://
                    ConStr = "DB1.DBX350.0"; //加压阀
                    break;
                case 25://
                    ConStr = "DB1.DBX342.0"; //回水箱气动阀
                    break;

                case 26://
                    ConStr = "DB1.DBX344.0"; //排水阀
                    break;
                case 27://
                    ConStr = "DB1.DBX346.0"; //循环泵
                    break;
                case 28://
                    ConStr = "DB1.DBX280.2"; //加热
                    break;
                case 29://
                    ConStr = "DB1.DBX280.3"; //冷却
                    break;
                case 30://
                    ConStr = "DB1.DBX200.6"; //心跳
                    break;
                case 31://
                    ConStr = "DB1.DBX352.0"; //泄压阀
                    break;
                case 32://
                    ConStr = "DB1.DBX280.0"; //自动加压
                    break;
                case 33://
                    ConStr = "DB1.DBX280.1"; //自动泄压
                    break;
                case 34://
                    ConStr = "DB1.DBX356.0"; //风冷/模温机
                    break;
                case 35://
                    ConStr = "DB1.DBX280.6"; //启用控温
                    break;
            }
            PLC1.Write(ConStr, Value);
        }


        /// <summary>
        /// 写入报警信息到PLC
        /// </summary>
        /// <param name="Station">工站编号</param>
        /// <param name="Value">报警代码</param>
        public void WiterPLCAlarm(int Station, short Value)
        {
            string ConStr = "";        // PLC地址字符串

            switch (Station)
            {
                case 0:// 
                    ConStr = "DB1.DBW312";   // OP1报警地址

                    break;
                case 1:// 
                    ConStr = "DB1.DBW314";   // OP2报警地址

                    break;
                case 2:// 
                    ConStr = "DB1.DBW316";   // OP3报警地址
                    break;
                case 3:// 
                    ConStr = "DB1.DBW318";   // OP4报警地址
                    break;
                case 4:// 
                    ConStr = "DB1.DBW320";   // OP5报警地址
                    break;
                case 5:// 
                    ConStr = "DB1.DBW322";   // OP6报警地址
                    break;
            }
            PLC1.Write(ConStr, (short)Value);  // 执行PLC写入操作
        }



        // ========== LIN通信方法 ==========

        /// <summary>
        /// 打开并初始化LIN设备
        /// </summary>
        public void Open_Init_Lin()
        {

            //扫描查找设备
            DevNum = USB_DEVICE.USB_ScanDevice(DevHandles);
            if (DevNum != 3)
            {
                LINState[0] = "未找到LIN设备";
                return;
            }

            else
            {
                LINState[0] = "找到3个LIN设备完成";
                LINState[6] = "1";
            }

            // 设备匹配
            string[] S = new string[6];
            S[0] = Convert.ToString(DevHandles[0], 16);
            S[1] = Convert.ToString(DevHandles[1], 16);
            S[2] = Convert.ToString(DevHandles[2], 16);
            for (int i = 0; i < 3; i++)
            {
                if (S[i].ToUpper() == Lin_Name[0])
                {
                    DevHandle[0] = DevHandles[i];
                }
                if (S[i].ToUpper() == Lin_Name[1])
                {
                    DevHandle[1] = DevHandles[i];
                }
                if (S[i].ToUpper() == Lin_Name[2])
                {
                    DevHandle[2] = DevHandles[i];
                }

            }

            //打开设备
            bool[] state = new bool[50];
            state[0] = USB_DEVICE.USB_OpenDevice(DevHandle[0]);
            state[1] = USB_DEVICE.USB_OpenDevice(DevHandle[1]);
            state[2] = USB_DEVICE.USB_OpenDevice(DevHandle[2]);


            if (state[0] && state[1] && state[2])
            {
                LINState[1] = "打开LIN设备完成";
                LINState[7] = "1";
            }
            else
            {
                LINState[1] = "打开LIN设备失败";
                return;
            }


            // 初始化配置LIN
            ret11[0] = USB2LIN_EX.LIN_EX_Init(DevHandles[0], LINIndex[0], 19200, 1);
            ret11[1] = USB2LIN_EX.LIN_EX_Init(DevHandles[0], LINIndex[1], 19200, 1);
            ret11[2] = USB2LIN_EX.LIN_EX_Init(DevHandles[1], LINIndex[0], 19200, 1);
            ret11[3] = USB2LIN_EX.LIN_EX_Init(DevHandles[1], LINIndex[1], 19200, 1);
            ret11[4] = USB2LIN_EX.LIN_EX_Init(DevHandles[2], LINIndex[0], 19200, 1);
            ret11[5] = USB2LIN_EX.LIN_EX_Init(DevHandles[2], LINIndex[1], 19200, 1);

            // 检查初始化结果
            if ((ret11[0] != USB2LIN_EX.LIN_EX_SUCCESS) ||
                (ret11[1] != USB2LIN_EX.LIN_EX_SUCCESS) ||
                (ret11[2] != USB2LIN_EX.LIN_EX_SUCCESS) ||
                (ret11[3] != USB2LIN_EX.LIN_EX_SUCCESS) ||
                (ret11[4] != USB2LIN_EX.LIN_EX_SUCCESS) ||
                (ret11[5] != USB2LIN_EX.LIN_EX_SUCCESS)
               )
            {
                LINState[2] = "配置LIN设置失败";

                return;
            }
            else
            {
                LINState[2] = "初始化配置LIN完成";
                LINState[8] = "1";
            }

            // 总体状态检查
            if (LINState[6] == "1" && LINState[7] == "1" && LINState[8] == "1")
            {
                LINState[9] = "1";
            }
        }


        /// <summary>
        /// 发送LIN数据
        /// </summary>
        /// <param name="HandleNumber">句柄编号</param>
        /// <param name="Idex">索引</param>
        /// <param name="Ddta_Send">发送数据</param>
        /// <param name="ID">LIN ID</param>
        public void Send_Lin(int HandleNumber, int Idex, byte[] Ddta_Send, byte ID)
        {
            ret1 = USB2LIN_EX.LIN_EX_MasterWrite(DevHandle[HandleNumber], LINIndex[Idex], ID, Ddta_Send, (byte)Ddta_Send.Length, (byte)1);
            if (ret1 != USB2LIN_EX.LIN_EX_SUCCESS)
            {
                // UpdateList("Write LIN failed!");     // 写入失败处理
                return;
            }
            else
            {
                // UpdateList("Write LIN Success!");    // 写入成功处理
            }
        }




        /// <summary>
        /// 读取LIN总线数据
        /// </summary>
        /// <param name="HandleNumber">设备句柄编号</param>
        /// <param name="Idex">LIN通道索引</param>
        /// <param name="ID">LIN消息ID</param>
        /// <returns>解析后的数据字符串数组</returns>
        public string[] Read_Lin(int HandleNumber, int Idex, byte ID)
        {
            string[] RevStr = new string[11] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" };         // 返回数据数组
            int[] FL = new int[4];     // 临时标志数组

            byte[] DataBuffer_Read = new byte[8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };            // 数据读取缓冲区
            ret = USB2LIN_EX.LIN_EX_MasterRead(DevHandle[HandleNumber], LINIndex[Idex], ID, DataBuffer_Read);   // 执行LIN读取

            string Str2 = "";                // 原始数据字符串
            string[] Str1 = new string[8];   // 字节数据字符串数组
            if (ret < 0)
            {
                // 读取失败
                // UpdateList("Read LIN failed!");
                RevStr[9] = "0";    // 设置读取状态为失败
            }
            else if (ret == 0)
            {
                // 从设备无响应
                RevStr[9] = "0";    // 设置读取状态为失败
                //UpdateList("The slave machine is not responding!");
            }
            else
            {
                for (int i = 0; i < ret; i++)
                {
                    // 读取成功，处理数据
                    Str1[i] = DataBuffer_Read[i].ToString("X2");  // 将字节转换为16进制字符串
                    Str2 = Str2 + " " + Str1[i];                  // 拼接原始数据字符串
                }

                // 将每个字节转换为二进制字符串并补齐8位
                string B1 = Convert.ToString(DataBuffer_Read[0], 2).PadLeft(8, '0').Trim();
                string B2 = Convert.ToString(DataBuffer_Read[1], 2).PadLeft(8, '0').Trim();
                string B3 = Convert.ToString(DataBuffer_Read[2], 2).PadLeft(8, '0').Trim();
                string B4 = Convert.ToString(DataBuffer_Read[3], 2).PadLeft(8, '0').Trim();
                string B5 = Convert.ToString(DataBuffer_Read[4], 2).PadLeft(8, '0').Trim();
                string B6 = Convert.ToString(DataBuffer_Read[5], 2).PadLeft(8, '0').Trim();
                string B7 = Convert.ToString(DataBuffer_Read[6], 2).PadLeft(8, '0').Trim();
                string B8 = Convert.ToString(DataBuffer_Read[7], 2).PadLeft(8, '0').Trim();

                // 反转二进制字符串（低位在前转为高位在前）
                string C1 = ReverseString(B1);
                string C2 = ReverseString(B2);
                string C3 = ReverseString(B3);
                string C4 = ReverseString(B4);
                string C5 = ReverseString(B5);
                string C6 = ReverseString(B6);
                string C7 = ReverseString(B7);
                string C8 = ReverseString(B8);

                // 从参数数组中获取数据位置和缩放系数
                int A1 = (int)(Parameterfloat[120]);   // 目标转速数据位置
                int A2 = (int)(Parameterfloat[121]);   // 实际转速数据位置
                int A3 = (int)(Parameterfloat[122]);   // 电压数据位置
                int A4 = (int)(Parameterfloat[123]);   // 温度数据位置
                int A5 = (int)(Parameterfloat[124]);   // 电流数据位置


                // 计算实际物理值
                double Sp1 = Convert.ToInt32(DataBuffer_Read[A1]) * Parameterfloat[130];   //目标转速
                double Sp2 = Convert.ToInt32(DataBuffer_Read[A2]) * Parameterfloat[131];   //实际转速
                double V = Convert.ToInt32(DataBuffer_Read[A3]) * Parameterfloat[132];     // 电压
                double T = Convert.ToInt32(DataBuffer_Read[A4]) * Parameterfloat[133] + Parameterfloat[162];   // 温度（带偏移）
                double A = Convert.ToInt32(DataBuffer_Read[A5]) * Parameterfloat[134];     // 电流

                // 限制转速在100以内
                if (Sp1 > 100)
                {
                    Sp1 = 100;
                }
                if (Sp2 > 100)
                {
                    Sp2 = 100;
                }

                // 填充返回数据数组
                RevStr[0] = Sp1.ToString("0");   // 目标转速
                RevStr[1] = Sp2.ToString("0");   // 实际转速
                RevStr[2] = V.ToString("0.0");   // 电压
                RevStr[3] = T.ToString("0.0");   // 温度
                RevStr[4] = A.ToString("0.0");   // 电流
                RevStr[8] = Str2;                // 原始数据字符串
                RevStr[9] = "1";                 // 读取成功标志
                RevStr[10] = C1 + C2 + C3 + C4 + C5 + C6 + C7 + C8;   // 完整的二进制数据
            }
            return RevStr;   // 返回解析后的数据
        }


        /// <summary>
        /// 关闭LIN设备连接
        /// </summary>
        public void CloseLIN()
        {
            USB_DEVICE.USB_CloseDevice(DevHandle[0]);   // 关闭第一个LIN设备
            USB_DEVICE.USB_CloseDevice(DevHandle[1]);   // 关闭第二个LIN设备
        }


        /// <summary>
        /// 根据工站编号获取对应的LIN接收数据数组
        /// </summary>
        /// <param name="Station">工站编号</param>
        /// <returns>对应的LIN接收数据数组</returns>
        public string[] LINRead(int Station)
        {
            string[] DB = new string[9] { "", "", "", "", "", "", "", "", "" };  // 默认返回空数组
            switch (Station)
            {
                case 0:
                    DB = LINR0;  // 工站0的LIN数据
                    break;
                case 1:
                    DB = LINR1;  // 工站1的LIN数据
                    break;
                case 2:
                    DB = LINR2;  // 工站2的LIN数据
                    break;
                case 3:
                    DB = LINR3;  // 工站3的LIN数据
                    break;
                case 4:
                    DB = LINR4;  // 工站4的LIN数据
                    break;
                case 5:
                    DB = LINR5;  // 工站5的LIN数据
                    break;
                case 6:
                    DB = LINR6;  // 工站6的LIN数据
                    break;
                case 7:
                    DB = LINR7;  // 工站7的LIN数据
                    break;
                case 8:
                    DB = LINR8;  // 工站8的LIN数据
                    break;
                case 9:
                    DB = LINR9;  // 工站9的LIN数据
                    break;
            }
            return DB;           // 返回对应的LIN数据数组
        }


        /// <summary>
        /// 设置LIN数据缓冲区中的速度值
        /// </summary>
        /// <param name="Station">工站编号</param>
        /// <param name="Idex">速度模式索引</param>
        /// <param name="SpeedSet">设定速度值</param>
        /// <returns>实际设置的速度值</returns>
        public float LIN_DataBufferSet(int Station, int Idex, float SpeedSet)
        {
            float SpeedSetRTN = 0;                       // 返回的实际速度值
            float Speed0 = Parameterfloat[100];          // 速度参数0
            float Speed1 = Parameterfloat[100];          // 速度参数1
            float Speed2 = Parameterfloat[100];          // 速度参数2
            float Tme_Set = Parameterfloat[82];          // 时间设定参数
            int Len = (int)(Parameterfloat[213]);        // 数据缓冲区长度
            int Position = (int)(Parameterfloat[260]);   // 速度数据在缓冲区中的位置
            float accuracy = Parameterfloat[261];        // 精度参数


            DataBuffersArrayLIN[Station] = new byte[Len];// 初始化指定工站的数据缓冲区

            // 根据速度模式索引设置不同的速度值
            if (Idex == 0)
            {
                DataBuffersArrayLIN[Station][Position] = (byte)(Math.Round(Speed0 / 0.4));    // 设置速度模式0
                SpeedSetRTN = Speed0;    // 返回实际设置的速度值
            }
            else if (Idex == 1)
            {
                DataBuffersArrayLIN[Station][Position] = (byte)(Math.Round(Speed1 / 0.4));    // 设置速度模式1
                SpeedSetRTN = Speed1;    // 返回实际设置的速度值
            }
            else if (Idex == 2)
            {
                DataBuffersArrayLIN[Station][Position] = (byte)(Math.Round(Speed2 / 0.4));    // 设置速度模式2
                SpeedSetRTN = Speed2;    // 返回实际设置的速度值
            }
            else if (Idex == 4)
            {
                DataBuffersArrayLIN[Station][Position] = (byte)(Math.Round(SpeedSet / 0.4));  // 设置自定义速度
                SpeedSetRTN = SpeedSet;  // 返回实际设置的速度值
            }
            else if (Idex == 5)
            {
                DataBuffersArrayLIN[Station][Position] = (byte)(Math.Round(0 / 0.4));         // 设置速度为0（停止）
                SpeedSetRTN = 0;         // 返回实际设置的速度值
            }
            DataBuffersArrayLIN[Station][2] = (byte)(Math.Round(90.0));   // 设置油温为90度
            return SpeedSetRTN;          // 返回实际设置的速度值
        }



        // ========== 文件操作方法 ==========

        /// <summary>
        /// 删除文件夹内所有文件
        /// </summary>
        /// <param name="PT">图片框</param>
        /// <param name="path">文件夹路径</param>
        public void Deleteflie(PictureBox PT, string path)
        {
            foreach (string file in Directory.GetFiles(path))
            {
                System.IO.File.Delete(file);
                PT.Image = null;
            }
        }


        /// </summary>
        /// <param name="PT">图片框</param>
        /// <param name="Pathsave">保存路径</param>
        /// <param name="PathRead">读取路径</param>
        /// <param name="State">状态</param>
        /// <param name="Code">代码</param>
        /// <returns>处理结果</returns>
        public string PictureHandle(PictureBox PT, string Pathsave, string PathRead, int State, string Code)
        {
            lock (this)
            {
                try
                {
                    // 读取图片文件
                    FileStream fileStream = new FileStream(PathRead, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    PT.Image = Image.FromStream(fileStream);


                    // 根据状态确定结果字符串
                    string str = "";
                    if (State == 1)
                    {
                        str = "OK";
                    }
                    else
                    {
                        str = "NG";
                    }

                    // 生成文件名
                    Time = DateTime.Now.ToLocalTime().ToString("yyyyMMdd HH:mm:ss");
                    string Na = Path.Combine(Time, "#", Code, "#", str);
                    string Na1 = GetNumberAlpha(Na);     // 过滤非法字符


                    // 创建日期文件夹
                    string Data = System.DateTime.Now.ToString("D");
                    string Na2 = Path.Combine(Pathsave, Data);
                    if (!Directory.Exists(Na2))
                    {
                        //创建文件夹
                        try
                        {
                            Directory.CreateDirectory(Na2);
                        }
                        catch (Exception ex)
                        {
                        }
                    }

                    // 保存图片
                    string[] paths = { Na2, Na1 + ".jpg" };
                    string fullPath = Path.Combine(paths);
                    PT.Image.Save(fullPath);

                    fileStream.Close();
                    fileStream.Dispose();
                    return "";
                }
                catch (Exception ex) { return ex.ToString(); }
            }

        }

        /// <summary>
        /// 检查文件夹是否为空
        /// </summary>
        /// <param name="folderPath">文件夹路径</param>
        /// <returns>true表示文件夹为空，false表示不为空</returns>
        public static bool IsFolderEmpty(string folderPath)
        {
            // 检查路径是否有效  
            if (!Directory.Exists(folderPath))
            {
                throw new DirectoryNotFoundException("指定的文件夹不存在。");   // 抛出目录不存在异常
            }
            // 使用Enumerable.Empty来判断文件夹是否包含任何文件或子文件夹  
            return !Directory.EnumerateFiles(folderPath, "*", SearchOption.AllDirectories).Any();
        }

        /// <summary>
        /// 科学计数法转换
        /// </summary>
        /// <param name="strData">字符串数据</param>
        /// <returns>双精度数值</returns>
        private double ChangeDataToD(string strData)
        {
            decimal dData = 0.0M;
            try
            {
                if (strData.Contains("E") || strData.Contains("e"))
                {
                    strData = strData.Substring(0, strData.Length - 1).Trim();
                    dData = Convert.ToDecimal(Decimal.Parse(strData.ToString(), System.Globalization.NumberStyles.Float));
                }
                else
                {
                    dData = decimal.Parse(strData);
                }
            }
            catch (Exception)
            {
                dData = 0;
            }
            return double.Parse(dData.ToString());
        }

        /// <summary>
        /// 文本框状态更新
        /// </summary>
        /// <param name="TB">文本框</param>
        /// <param name="Str">文本</param>
        /// <param name="Idex">状态索引</param>
        public void UpdateTB(TextBox TB, string Str, int Idex)
        {
            switch (Idex)
            {
                case 1:       // 绿色-正常
                    TB.BackColor = Color.Lime;
                    TB.Text = Str;
                    break;
                case 2:       // 红色-异常
                    TB.BackColor = Color.Red;
                    TB.Text = Str;
                    break;
                case 3:       // 黄色-警告
                    TB.BackColor = Color.Yellow;
                    TB.Text = Str;
                    break;
                case 4:
                    TB.BackColor = Color.Gray;
                    TB.Text = Str;
                    break;
                case 5:
                    TB.Text = Str;
                    break;
                case 6:
                    TB.BackColor = Color.Gray;
                    TB.Text = "等待中";
                    break;
                case 7:
                    TB.BackColor = Color.Yellow;
                    TB.Text = "测试中";
                    break;
                case 8:       // 绿色-测试合格
                    TB.BackColor = Color.Lime;
                    TB.Text = "测试完成，测试合格";
                    break;
                case 9:       // 红色-测试不合格
                    TB.BackColor = Color.Red;
                    TB.Text = "测试完成，测试不合格";
                    break;
                case 10:
                    TB.BackColor = Color.Yellow;
                    TB.Text = "开始测试";
                    break;
                case 11:
                    TB.BackColor = Color.Yellow;
                    TB.Text = "伺服电缸下压中";
                    break;
                case 12:
                    TB.BackColor = Color.Yellow;
                    TB.Text = "伺服电缸下压到位";
                    break;
                case 13:
                    TB.BackColor = Color.Yellow;
                    TB.Text = "ATEQ泄露仪测试中";
                    break;
                case 15:
                    TB.BackColor = Color.Yellow;
                    TB.Text = "伺服电缸上升中";
                    break;
                case 16:
                    TB.BackColor = Color.Yellow;
                    TB.Text = "伺服电缸上升到位";
                    break;
            }
        }



        /// <summary>
        /// 数据库基础操作
        /// </summary>
        /// <param name="Idex">操作类型索引</param>
        public void BC_DatabaseOperation(int Idex)
        {
            switch (Idex)
            {

                case 0:
                    SQL1.CreateDataBase(SQL1.DatabaseStr);  // 创建数据库
                    break;
                case 1:
                    SQL1.CreateDataTable30(SQL1.DatabaseStr, SQL1.ParameterSetTableStr);  // 创建30字段参数表
                    break;
                case 2:
                    SQL1.CreateDataTable7(SQL1.DatabaseStr, SQL1.ParameterSetTableStr);   // 创建7字段参数表
                    break;
                case 3:
                    SQL1.CreateDataTable8(SQL1.DatabaseStr, SQL1.TestDataTable);          // 创建8字段测试数据表
                    break;
            }
        }


        /// <summary>
        /// 从数据库读取生产统计数量
        /// </summary>
        /// <param name="Idex">统计类型索引</param>
        /// <param name="StartTime">开始时间</param>
        /// <param name="EndTime">结束时间</param>
        public void intBC_DatabaseNum(int Idex, DateTime StartTime, DateTime EndTime)
        {

            switch (Idex)
            {
                case 0:
                    Left_yield = SQL1.ReadDtata4(SQL1.DatabaseStr, SQL1.TestDataTable, StartTime, EndTime);          // 读取左工位产量
                    break;
                case 1:
                    Right_yield = SQL1.ReadDtata5(SQL1.DatabaseStr, SQL1.TestDataTable, StartTime, EndTime);         // 读取右工位产量
                    break;
                case 2:
                    Left_Qualified_Num = SQL1.ReadDtata6(SQL1.DatabaseStr, SQL1.TestDataTable, StartTime, EndTime);  // 读取左工位合格数
                    break;
                case 3:
                    Right_Qualified_Num = SQL1.ReadDtata7(SQL1.DatabaseStr, SQL1.TestDataTable, StartTime, EndTime); // 读取右工位合格数
                    break;
            }

        }



        /// <summary>
        /// 更新生产统计数据显示
        /// </summary>
        /// <param name="Idex">操作类型索引</param>
        /// <param name="Station">工站编号</param>
        /// <param name="TB">合格率标签</param>
        /// <param name="TB2">产量标签</param>
        public void intBC_DatabaseNum0(int Idex, int Station, Label TB, Label TB2)
        {
            switch (Idex)
            {
                case 0:   //测试合格
                    if (Station == 0)
                    {
                        Left_yield += 1;            // 左工位产量加1
                        Left_Qualified_Num += 1;    // 左工位合格数加1


                        // 计算左工位合格率
                        Left_Qualified_Rate = 100.0f * (float)Left_Qualified_Num / Left_yield;
                        TB.Text = "合格率：" + Left_Qualified_Rate.ToString("0.0") + "%";      // 更新合格率显示
                        TB2.Text = "班次产量：" + Left_yield.ToString();                       // 更新产量显示
                    }
                    else
                    {
                        Right_yield += 1;          // 右工位产量加1
                        Right_Qualified_Num += 1;  // 右工位合格数加1


                        // 计算右工位合格率
                        Right_Qualified_Rate = 100.0f * (float)Right_Qualified_Num / Right_yield;
                        TB.Text = Right_Qualified_Rate.ToString("0.0") + "%";     // 更新合格率显示
                        TB2.Text = Right_yield.ToString();                        // 更新产量显示
                    }
                    break;

                case 1:   //测试不合格
                    if (Station == 0)
                    {

                        Left_yield += 1;// 重新计算左工位合格率

                        // 重新计算左工位合格率
                        Left_Qualified_Rate = Left_Qualified_Num / Left_yield;
                        Left_Qualified_Rate = 100.0f * (float)Left_Qualified_Num / Left_yield;


                        TB.Text = "合格率：" + Left_Qualified_Rate.ToString("0.0") + "%";  // 更新合格率显示
                        TB2.Text = "班次产量：" + Left_yield.ToString();                   // 更新产量显示
                    } 
                    else
                    {
                        Right_yield += 1;       // 右工位产量加1（不合格也计入总产量）

                        // 重新计算右工位合格率
                        Right_Qualified_Rate = Right_Qualified_Num / Right_yield;
                        Right_Qualified_Rate = 100.0f * (float)Right_Qualified_Num / Right_yield;


                        TB.Text = Right_Qualified_Rate.ToString("0.0") + "%";    // 更新合格率显示
                        TB2.Text = Right_yield.ToString();                       // 更新产量显示
                    }
                    break;
                case 2:   //登录时更新显示
                    if (Station == 0)
                    {
                        if (Left_yield == 0)
                        {
                            Left_Qualified_Rate = 0;  // 产量为0时合格率为0
                        }
                        else
                        {
                            // 计算左工位合格率
                            Left_Qualified_Rate = 100.0f * (float)Left_Qualified_Num / Left_yield;
                        }
                        TB.Text = "合格率：" + Left_Qualified_Rate.ToString("0.0") + "%";   // 更新合格率显示
                        TB2.Text = "班次产量：" + Left_yield.ToString();                    // 更新产量显示
                    }
                    else
                    {
                        if (Right_yield == 0)
                        {
                            Right_Qualified_Rate = 0;     // 产量为0时合格率为0
                        }
                        else
                        {
                            // 计算右工位合格率
                            Right_Qualified_Rate = 100.0f * (float)Right_Qualified_Num / Right_yield;
                        }
                        TB.Text = Right_Qualified_Rate.ToString("0.0") + "%";    // 更新合格率显示
                        TB2.Text = Right_yield.ToString();                       // 更新产量显示
                    }
                    break;
            }
        }


        /// <summary>
        /// 从数据库读取月度或年度生产数据
        /// </summary>
        /// <param name="Idex">查询类型索引</param>
        /// <param name="Year0">年份</param>
        /// <param name="Month0">月份</param>
        /// <returns>生产数据数组</returns>
        public int[] intBC_DatabaseNum1(int Idex, int Year0, int Month0)
        {
            int[] Num = new int[32];     // 返回数据数组
            switch (Idex)
            {
                case 1:
                    // 读取指定年月的生产数据
                    Num = SQL1.ReadDtata17(SQL1.DatabaseStr, SQL1.TestDataTable, Year0, Month0);
                    break;
                case 2:
                    // 读取指定年份的月度生产数据
                    Num = SQL1.ReadDtata18(SQL1.DatabaseStr, SQL1.TestDataTable, Year0);
                    break;
            }
            return Num;  // 返回生产数据数组
        }


        /// <summary>
        /// 执行SQL数据插入操作
        /// </summary>
        /// <param name="Station">工站编号</param>
        /// <param name="Idex">测试结果索引</param>
        /// <param name="Data1">测试数据数组</param>
        public void SQlOp0(int Station, int Idex, string[] Data1)
        {
            string[] Str = new string[21];          // SQL插入数据数组
            // 填充基础信息
            Str[0] = DateTime.Now.ToString("G");    // 当前时间
            Str[1] = StationCodeStr[Station];       // 工站代码
            // 设置工站名称
            if (Station == 0)
            {
                Str[2] = "左工位";   // 左工位标识
            }
            else
            {
                Str[2] = "右工位";   // 右工位标识
            }

            // 填充测试数据
            Str[3] = Data1[0];
            Str[4] = Data1[1];
            Str[5] = Data1[2];
            Str[6] = Data1[3];
            Str[7] = Data1[4];
            Str[8] = Data1[5];
            Str[9] = Data1[6];
            Str[10] = Data1[7];
            Str[11] = Data1[8];
            Str[12] = Data1[9];
            Str[13] = Data1[10];
            Str[14] = Data1[11];
            Str[15] = Data1[12];
            Str[16] = Data1[13];
            Str[17] = Data1[14];
            Str[18] = Data1[15];

            // 设置测试结果
            if (Idex == 1)
            {
                Str[19] = "OK";      // 测试合格
            }
            else if (Idex == 2)
            {
                Str[19] = "NG";      // 测试不合格
            }

            Str[20] = FL_Name;       // 生产线名称
            SQL1.InsertData31(Str);  // 执行SQL插入操作

        }


  


        /// <summary>
        /// 性能报告
        /// </summary>
        /// <param name="temp"></param>
        /// <param name="atmo"></param>
        /// <param name="Equipmentnum"></param>
        /// <param name="code"></param>
        /// <param name="station"></param>
        /// <param name="Str1"></param>
        /// <param name="Str2"></param>
        /// <param name="Str3"></param>
        /// <param name="Str4"></param>
        /// <param name="Flow"></param>
        /// <param name="Speed"></param>
        /// <param name="inP"></param>
        /// <param name="OutP"></param>
        /// <param name="Left"></param>
        /// <param name="V"></param>
        /// <param name="C"></param>
        /// <param name="inPower"></param>
        /// <param name="outPower"></param>
        /// <param name="XL"></param>
        /// <returns></returns>
        public bool DataToExcel(string[] Str0, List<float> V, List<float> C, List<double> Flow, List<double> Left, List<float> Diff, List<float> inP, List<float> Tempera, List<double> inPower, List<double> outPower, List<double> XL)
        {
            try
            {


                // 第一步：读取文件流
                NPOI.SS.UserModel.IWorkbook workbook;
                using (FileStream stream = new FileStream(ReadEXcll, FileMode.Open, FileAccess.ReadWrite))
                {
                    workbook = new NPOI.XSSF.UserModel.XSSFWorkbook(stream);
                }

                // 第二步：创建新数据行
                NPOI.SS.UserModel.ISheet sheet = workbook.GetSheetAt(0);
                NPOI.SS.UserModel.IRow row = sheet.CreateRow(sheet.LastRowNum + 1);
                NPOI.SS.UserModel.ICell cell;

                // 创建单元格样式
                NPOI.SS.UserModel.ICellStyle cellStyle = workbook.CreateCellStyle();
                cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                cellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
                cellStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
                cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00");

                //6到25行


                try
                {
                    for (int i = 8; i < (V.Count() + 8); i++)
                    {

                        var _sheetCellValue1 = sheet.GetRow(i).GetCell(1);
                        _sheetCellValue1.SetCellValue(V[i - 6]);

                        var _sheetCellValue2 = sheet.GetRow(i).GetCell(3);
                        _sheetCellValue2.SetCellValue(C[i - 6]);

                        var _sheetCellValue3 = sheet.GetRow(i).GetCell(4);
                        _sheetCellValue3.SetCellValue(Flow[i - 6]);

                        var _sheetCellValue4 = sheet.GetRow(i).GetCell(5);
                        _sheetCellValue4.SetCellValue(Left[i - 6]);

                        var _sheetCellValue5 = sheet.GetRow(i).GetCell(7);
                        _sheetCellValue5.SetCellValue(Diff[i - 6]);

                        var _sheetCellValue6 = sheet.GetRow(i).GetCell(8);
                        _sheetCellValue6.SetCellValue(inP[i - 6]);

                        var _sheetCellValue7 = sheet.GetRow(i).GetCell(9);
                        _sheetCellValue7.SetCellValue(Tempera[i - 6]);

                        var _sheetCellValue8 = sheet.GetRow(i).GetCell(11);
                        _sheetCellValue8.SetCellValue(inPower[i - 6]);

                        var _sheetCellValue9 = sheet.GetRow(i).GetCell(12);
                        _sheetCellValue9.SetCellValue(outPower[i - 6]);

                        var _sheetCellValue10 = sheet.GetRow(i).GetCell(13);
                        _sheetCellValue10.SetCellValue(XL[i - 6]);

                    }
                }
                catch (Exception ex) { }

                var _sheetCellValue11 = sheet.GetRow(2).GetCell(2);//行与列
                _sheetCellValue11.SetCellValue(_sheetCellValue11 + Str0[0]);


                var _sheetCellValue12 = sheet.GetRow(2).GetCell(5);//行与列
                _sheetCellValue12.SetCellValue(_sheetCellValue12 + Str0[1]);


                var _sheetCellValue13 = sheet.GetRow(2).GetCell(9);
                _sheetCellValue13.SetCellValue(_sheetCellValue13 + Str0[2]);

                var _sheetCellValue14 = sheet.GetRow(2).GetCell(13);
                _sheetCellValue14.SetCellValue(_sheetCellValue14 + Str0[3]);

                var _sheetCellValue15 = sheet.GetRow(3).GetCell(2);
                _sheetCellValue15.SetCellValue(_sheetCellValue15 + Str0[4]);//

                var _sheetCellValue16 = sheet.GetRow(3).GetCell(5);
                _sheetCellValue16.SetCellValue(_sheetCellValue16 + Str0[5]);//

                var _sheetCellValue17 = sheet.GetRow(3).GetCell(9);
                _sheetCellValue17.SetCellValue(_sheetCellValue17 + Str0[6]);//


                var _sheetCellValue18 = sheet.GetRow(2).GetCell(18);
                _sheetCellValue18.SetCellValue(_sheetCellValue18 + Str0[7]);//


                string TimeStr = DateTime.Now.ToString("yyyyMMddHHmmss");

                string BAC = DataSave(SavePT[2]);
                string Str = BAC + "\\性能测试-" + TimeStr + ".xls";



                cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00");
                // 第三步：写入文件流
                using (FileStream stream = new FileStream(Str, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    workbook.Write(stream);
                    workbook.Close();
                }

                return true;
            }
            catch (Exception ex) { return false; }

        }



        /// <summary>
        /// 生成有效文件名（过滤非法字符）
        /// </summary>
        /// <param name="text">原始文本</param>
        /// <returns>有效文件名</returns>
        public static string MakeValidFileName(string text)
        {
            StringBuilder str = new StringBuilder();     // 字符串构建器
            var invalidFileNameChars = Path.GetInvalidFileNameChars();  // 获取非法文件名字符

            // 遍历每个字符，只保留有效字符
            foreach (var c in text)
            {
                if (!invalidFileNameChars.Contains(c))
                {
                    str.Append(c);  // 添加有效字符
                }
            }
            return str.ToString();  // 返回有效文件名
        }



        /// <summary>
        /// 文本数据写入文件
        /// </summary>
        /// <param name="Path">文件路径</param>
        /// <param name="Str">要写入的文本</param>
        /// <param name="ADD">是否追加模式（true追加，false覆盖）</param>
        public void TxtData(string Path, string Str, bool ADD)
        {
            //string filePath0 = @"C:\Users\Administrator\Desktop\新建文本文档 (8).txt"; // 替换为你的文件路径  
            //string newData0 = "这是新追加的数据111。\n"; // 你要追加的数据  
            // 使用using语句来确保StreamWriter在不再需要时能被正确关闭和释放  
            using (StreamWriter writer = new StreamWriter(Path, ADD)) // 第二个参数为true表示追加模式  
            {
                writer.WriteLine(Str); // 写入数据，并自动添加换行符  
            }
        }



        /// <summary>
        /// 创建数据保存目录
        /// </summary>
        /// <param name="Path0">基础路径</param>
        /// <returns>完整的保存路径</returns>
        public string DataSave(string Path0)
        {

            string Data = System.DateTime.Now.ToString("D");  // 当前日期字符串
            string Na2 = Path.Combine(Path0, Data);           // 组合完整路径

            // 检查目录是否存在，不存在则创建
            if (!Directory.Exists(Na2))
            {
                //创建文件夹
                try
                {
                    Directory.CreateDirectory(Na2);  // 创建目录
                }
                catch (Exception ex)
                {}
            }
            return Na2;   // 返回完整路径
        }


        /// <summary>
        /// 从字符串中提取子串并转换为浮点数
        /// </summary>
        /// <param name="Str">原始字符串</param>
        /// <param name="StartIdex">起始索引</param>
        /// <param name="Length">提取长度</param>
        /// <returns>转换后的浮点数值</returns>
        public float StrSubstring(string Str, int StartIdex, int Length)
        {
            float Value = 0;            // 返回值

            // 检查字符串长度是否足够
            if (Str.Length > Length)
            {
                string ReStr = Str.Substring(StartIdex, Length);  // 提取子字符串
                int V1 = Convert.ToInt32(ReStr, 16);              // 16进制转换为整数
                Value = (float)V1 / 65535;                        // 归一化到0-1范围
            }
            return Value;
        }


        // ========== 数据处理方法 ==========

        /// <summary>
        /// 扬程换算
        /// </summary>
        /// <param name="InP">进口压力</param>
        /// <param name="OutP">出口压力</param>
        /// <returns>扬程值</returns>
        public double LiftConversion(float InP, float OutP)
        {
            //H=(p2-p1)/ρg+(v2²-v1²)/2g+z2-z1

            double H;

            if (InP >= -100 && InP <= 5000 && OutP >= -100 && OutP <= 5000)
            { 
                H = ((OutP - InP) * 10 / 98);   // 扬程计算公式

            }
            else
            {
                H = 0;
            }
            return H;
        }

        /// <summary>
        /// 计算输出功率
        /// </summary>
        /// <param name="L">流量</param>
        /// <param name="Diff">压差</param>
        /// <returns>输出功率</returns>
        public double OutputPower(double L, double Diff)
        {
            //水泵功率P=2.73HQ   H是扬程单位是米。Q是流量m3/h，功率是瓦
            //氟泵：W输出=Q（L/MIN）*0.001*60/3600*压差(Pa)
            double W;

            // W = 2.73 * F * L / 6;
            W = Diff * L * 60 / 3600;    // 功率计算公式
            if (W <= 0)
            {
                W = 0;
            }
            return W;
        }


        /// <summary>
        /// 远程数据库操作
        /// </summary>
        /// <param name="Idex">操作类型索引</param>
        public void SQlOp(int Idex)
        {
            SQL1.ReadDtata32("customer_user");  // 读取客户用户数据
        }



        /// <summary>
        /// 比较数值是否在上下限范围内
        /// </summary>
        /// <param name="UP">上限值</param>
        /// <param name="Down">下限值</param>
        /// <param name="Value">待比较值</param>
        /// <returns>0-在范围内，1-超过上限，2-低于下限</returns>
        public int CompareSize(float UP, float Down, float Value)
        {
            int T = 0;         // 返回结果

            if (Value > UP)
            {
                T = 1;         // 超过上限
            }
            else if (Value < Down)
            {
                T = 2;         // 低于下限
            }
            return T;          // 返回比较结果
        }


        /// <summary>
        /// 产量柱状图
        /// </summary>
        /// <param name="CR"></param>
        /// <param name="DP"></param>
        /// <param name="Idex"></param>
        public void ChartDisplay(Chart CR, DateTimePicker DP, int Idex, int[] DataNum)
        {
            CR.ChartAreas[0].AxisX.LabelStyle.Interval = 1;//设置X轴的值的间隔大小
            CR.Series[0].ChartType = SeriesChartType.Column;
            CR.Series[0].IsValueShownAsLabel = true;
            int Num = 0; ;
            CR.Series[0].Points.Clear();
            string[] Mon = new string[12] { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月" };
            CR.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.Transparent;//设置Y轴网格线颜色
            if (Idex == 0)
            {
                CR.ChartAreas[0].AxisY.Title = "产量（PCS）";
                CR.ChartAreas[0].AxisX.Title = "日期";
                int Year0 = DP.Value.Year;
                int Month0 = DP.Value.Month;
                Num = DateTime.DaysInMonth(Year0, Month0);//获得一个月天数
                CR.ChartAreas[0].AxisX.Maximum = Num + 0.5;
                for (int i = 1; i <= Num; i++)
                {
                    CR.Series[0].Points.AddXY(i, DataNum[i - 1]); // 这里添加的数据点是X轴日期对应的Y值，你可以根据需要修改这些值。  
                }
            }
            else
            {
                Num = 12;
                CR.ChartAreas[0].AxisX.Maximum = Num + 0.5;

                CR.ChartAreas[0].AxisY.Title = "产量（PCS）";
                CR.ChartAreas[0].AxisX.Title = "月份";

                for (int i = 1; i <= Num; i++)
                {
                    CR.Series[0].Points.AddXY(Mon[i - 1], DataNum[i - 1]); // 
                }
            }
        }





        /// <summary>
        /// 整点触发
        /// </summary>
        /// <param name="Value"></param>
        public void HourAction(ref int Value, string Path0)
        {
            if (Value == 2)
            {
                string[] lines = { DateTime.Now.ToString("yyyy-MM-dd HH ") };
                System.IO.File.WriteAllLines(Path0, lines);
                Value = 0;
            }
            string[] strs = File.ReadAllLines(Path0);
            if (strs[0] != DateTime.Now.ToString("yyyy-MM-dd HH "))
            {
                Value = 1;
            }
        }


        /// <summary>
        /// //16转2方法
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        static string HexString2BinString(string hexString)
        {
            try
            {
                string result = string.Empty;
                foreach (char c in hexString)
                {
                    int v = Convert.ToInt32(c.ToString(), 16);
                    int v2 = int.Parse(Convert.ToString(v, 2));
                    // 去掉格式串中的空格，即可去掉每个4位二进制数之间的空格，
                    result += string.Format("{0:d4} ", v2);
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw;
            }
        }


        /// <summary>
        /// 读取参数数据（空方法，待实现）
        /// </summary>
        /// <param name="Idex">参数索引</param
        public void ReadParameterData(int Idex)
        {  }



        /// <summary>
        /// 将秒数转换为时分秒格式字符串
        /// </summary>
        /// <param name="duration">总秒数</param>
        /// <returns>格式化的时间字符串</returns>
        public string sec_to_hms(long duration)
        {
            TimeSpan ts = new TimeSpan(0, 0, Convert.ToInt32(duration));  // 创建时间跨度对象
            string str = "";        // 返回字符串

            // 根据时间长度选择不同的格式
            if (ts.Hours > 0)
            {
                str = String.Format("{0:00}", ts.Hours) + ":" + String.Format("{0:00}", ts.Minutes) + ":" + String.Format("{0:00}", ts.Seconds);   // 时分秒格式
            }
            if (ts.Hours == 0 && ts.Minutes > 0)
            {
                str = "00:" + String.Format("{0:00}", ts.Minutes) + ":" + String.Format("{0:00}", ts.Seconds);   // 分秒格式
            }
            if (ts.Hours == 0 && ts.Minutes == 0)
            {
                str = "00:00:" + String.Format("{0:00}", ts.Seconds);  // 秒格式
            }
            return str;   // 返回格式化的时间字符串
        }


        /// <summary>
        /// 提取字符串中的数字、字母和连字符
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <returns>过滤后的字符串</returns>
        public static string GetNumberAlpha(string source)
        {
            string pattern = "[A-Za-z0-9-#]";      // 正则表达式模式：字母、数字、连字符
            string strRet = "";                    // 返回字符串
            MatchCollection results = Regex.Matches(source, pattern);  // 执行正则匹配

            // 遍历所有匹配结果
            foreach (var v in results)
            {
                strRet += v.ToString();   // 拼接匹配字符
            }
            return strRet;                // 返回过滤后的字符串
        }



        /// <summary>
        /// 将浮点数转换为字节数组
        /// </summary>
        /// <param name="data">浮点数值</param>
        /// <returns>字节数组</returns>
        public static byte[] ToByte(float data)
        {
            unsafe    // 使用不安全代码
            {
                byte* pdata = (byte*)&data;   // 获取浮点数的字节指针
                byte[] byteArray = new byte[sizeof(float)];  // 创建字节数组
                
                // 复制字节数据
                for (int i = 0; i < sizeof(float); ++i)
                    byteArray[i] = *pdata++;   // 逐个字节复制

                return byteArray;              // 返回字节数组
            }
        }


        /// <summary>
        /// Modbus CRC校验计算
        /// </summary>
        /// <param name="byteData">待校验字节数组</param>
        /// <returns>CRC校验码（2字节）</returns>
        public byte[] ToModbus(byte[] byteData)
        {
            byte[] CRC = new byte[2];    // CRC校验结果
             
            UInt16 wCrc = 0xFFFF;        // CRC初始值

            // 遍历每个字节
            for (int i = 0; i < byteData.Length; i++)
            {
                wCrc ^= Convert.ToUInt16(byteData[i]);  // 异或操作

                // 处理每个字节的8个位
                for (int j = 0; j < 8; j++)  
                {
                    if ((wCrc & 0x0001) == 1)    // 检查最低位
                    {
                        wCrc >>= 1;              // 右移一位
                        wCrc ^= 0xA001;          // 异或多项式
                    }
                    else
                    {
                        wCrc >>= 1;              // 右移一位
                    }
                }
            }

            CRC[1] = (byte)((wCrc & 0xFF00) >> 8);//高位在后
            CRC[0] = (byte)(wCrc & 0x00FF);       //低位在前
            return CRC;               // 返回CRC校验码
            return CRC; 
        }

        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>16进制字符串</returns>
        public string byteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            try
            {
                if (bytes != null)
                {
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        returnStr += bytes[i].ToString("X2");
                        returnStr += " ";   //两个16进制用空格隔开,方便看数据
                    }
                }
                return returnStr;
            }
            catch (Exception)
            {
                return returnStr;
            }
        }


        /// <summary>
        /// 字符串反转
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>反转后的字符串</returns>
        static string ReverseString(string input)
        {
            char[] charArray = input.ToCharArray();
            Array.Reverse(charArray);
            return new string(charArray);
        }


        /// <summary>
        /// 垃圾回收
        /// </summary>
        public void GarbageCollect()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }
    }
}
